import { defineStore } from "pinia";
import AliOssSdk from "ali-oss";
import type { Options as AliOssOptions, HeadObjectOptions } from "ali-oss";
import type { OssStoreState, OssAuth, FileAcl } from "@/stores/types/multipartOssTypes";
import { aliOssSecurityToken } from "@/apis/file";
import useFileUploadComplete from "@/stores/modules/fileUploadComplete";

const useMultipartOssStore = defineStore("oss", {
  state: (): OssStoreState => ({
    clientOssObj: null,
    clientOss: null
  }),
  actions: {
    async getAuth(): Promise<OssAuth> {
      try {
        const { data } = await aliOssSecurityToken();
        return {
          region: "oss-cn-hangzhou",
          bucket: "51-jzt-dev",
          accessKeyId: data.accessKeyId,
          accessKeySecret: data.accessKeySecret,
          stsToken: data.securityToken,
          refreshSTSToken: async () => {
            return await this.getAuth();
          },
          refreshSTSTokenInterval: 3600 * 1000
        };
      } catch (error) {
        console.error("Error fetching STS token:", error);
        throw new Error(`Failed to fetch STS token: ${String(error)}`);
      }
    },
    async getClientOss(): Promise<AliOssSdk> {
      if (!this.clientOssObj) {
        try {
          if (!this.clientOss) {
            this.clientOss = await this.getAuth();
          }
          this.clientOssObj = new AliOssSdk({
            ...this.clientOss
          } as AliOssOptions);
        } catch (error) {
          console.error("Error initializing OSS client:", error);
          throw new Error(`Failed to initialize OSS client: ${String(error)}`);
        }
      }
      return this.clientOssObj;
    },
    async submit(ObjName: string, fileData: File, uid: string): Promise<any> {
      try {
        const client = await this.getClientOss();
        return client.multipartUpload(ObjName, fileData, {
          progress: (percentage: number) => {
            useFileUploadComplete().setFileLoading(uid, percentage);
            console.log(`Upload progress: ${percentage}__${percentage * 100}%`);
          },
          parallel: 4,
          partSize: 1024 * 1024
        });
      } catch (error) {
        console.error("Error uploading file:", error);
        throw new Error(`Failed to upload file: ${String(error)}`);
      }
    },
    async setACL(ObjName: string, acl: FileAcl): Promise<void> {
      try {
        const client = await this.getClientOss();
        await client.putACL(ObjName, acl);
      } catch (error) {
        console.error("Error setting ACL:", error);
        throw new Error(`Failed to set ACL: ${String(error)}`);
      }
    },
    async signatureUrl(ObjName: string): Promise<string> {
      try {
        const client = await this.getClientOss();
        return client.signatureUrl(ObjName);
      } catch (error) {
        console.error("Error generating signature URL:", error);
        throw new Error(`Failed to generate signature URL: ${String(error)}`);
      }
    },
    async isExistObject(name: string, options: HeadObjectOptions = {}) {
      try {
        const client = await this.getClientOss();
        await client.head(name, options);
        return true;
      } catch (error: any) {
        return error?.code !== "NoSuchKey";
      }
    }
  }
});
export default useMultipartOssStore;
